import { Injectable, Logger } from "@nestjs/common";
import { RedisService } from "../../../services/redis.service";
import { GameType } from "../entities";
import { casinoConfig } from "../config/casino.config";

@Injectable()
export class CasinoCacheService {
  private readonly logger = new Logger(CasinoCacheService.name);
  private readonly keyPrefix = casinoConfig.redis.keyPrefix;

  constructor(private readonly redisService: RedisService) {}

  // ==================== 期数信息缓存 ====================

  /**
   * 缓存期数信息
   */
  async cacheRoundInfo(
    gameType: GameType,
    roundNumber: number,
    data: any
  ): Promise<void> {
    try {
      const key = `${this.keyPrefix}round:${gameType}:${roundNumber}`;
      const ttl = casinoConfig.redis.ttl.roundInfo;

      await this.redisService.set(key, JSON.stringify(data), ttl);
      this.logger.debug(`缓存期数信息: ${key}, TTL: ${ttl}秒`);
    } catch (error: any) {
      this.logger.error(`缓存期数信息失败:`, error?.message || error);
    }
  }

  /**
   * 获取缓存的期数信息
   */
  async getCachedRoundInfo(
    gameType: GameType,
    roundNumber: number
  ): Promise<any | null> {
    try {
      const key = `${this.keyPrefix}round:${gameType}:${roundNumber}`;
      const data = await this.redisService.get(key);

      if (data) {
        this.logger.debug(`命中期数信息缓存: ${key}`);
        return JSON.parse(data);
      }

      return null;
    } catch (error: any) {
      this.logger.error(`获取期数信息缓存失败:`, error?.message || error);
      return null;
    }
  }

  /**
   * 清除期数信息缓存
   */
  async clearRoundInfoCache(
    gameType: GameType,
    roundNumber: number
  ): Promise<void> {
    try {
      const key = `${this.keyPrefix}round:${gameType}:${roundNumber}`;
      await this.redisService.del(key);
      this.logger.debug(`清除期数信息缓存: ${key}`);
    } catch (error: any) {
      this.logger.error(`清除期数信息缓存失败:`, error?.message || error);
    }
  }

  // ==================== 用户余额缓存 ====================

  /**
   * 缓存用户余额
   */
  async cacheUserBalance(
    userId: number,
    gold: number,
    silver: number
  ): Promise<void> {
    try {
      const key = `${this.keyPrefix}balance:${userId}`;
      const ttl = casinoConfig.redis.ttl.userBalance;
      const data = { gold, silver, timestamp: Date.now() };

      await this.redisService.set(key, JSON.stringify(data), ttl);
      this.logger.debug(`缓存用户余额: ${key}, TTL: ${ttl}秒`);
    } catch (error: any) {
      this.logger.error(`缓存用户余额失败:`, error?.message || error);
    }
  }

  /**
   * 获取缓存的用户余额
   */
  async getCachedUserBalance(
    userId: number
  ): Promise<{ gold: number; silver: number } | null> {
    try {
      const key = `${this.keyPrefix}balance:${userId}`;
      const data = await this.redisService.get(key);

      if (data) {
        const balance = JSON.parse(data);
        // 检查缓存是否过期（5分钟内的数据认为是有效的）
        if (Date.now() - balance.timestamp < 5 * 60 * 1000) {
          this.logger.debug(`命中用户余额缓存: ${key}`);
          return { gold: balance.gold, silver: balance.silver };
        }
      }

      return null;
    } catch (error: any) {
      this.logger.error(`获取用户余额缓存失败:`, error?.message || error);
      return null;
    }
  }

  /**
   * 清除用户余额缓存
   */
  async clearUserBalanceCache(userId: number): Promise<void> {
    try {
      const key = `${this.keyPrefix}balance:${userId}`;
      await this.redisService.del(key);
      this.logger.debug(`清除用户余额缓存: ${key}`);
    } catch (error: any) {
      this.logger.error(`清除用户余额缓存失败:`, error?.message || error);
    }
  }

  // ==================== 排行榜缓存 ====================

  /**
   * 缓存排行榜数据
   */
  async cacheRankings(
    gameType: GameType,
    rankingType: string,
    page: number,
    data: any
  ): Promise<void> {
    try {
      const key = `${this.keyPrefix}rankings:${gameType}:${rankingType}:${page}`;
      const ttl = casinoConfig.redis.ttl.rankings;

      await this.redisService.set(key, JSON.stringify(data), ttl);
      this.logger.debug(`缓存排行榜数据: ${key}, TTL: ${ttl}秒`);
    } catch (error: any) {
      this.logger.error(`缓存排行榜数据失败:`, error?.message || error);
    }
  }

  /**
   * 获取缓存的排行榜数据
   */
  async getCachedRankings(
    gameType: GameType,
    rankingType: string,
    page: number
  ): Promise<any | null> {
    try {
      const key = `${this.keyPrefix}rankings:${gameType}:${rankingType}:${page}`;
      const data = await this.redisService.get(key);

      if (data) {
        this.logger.debug(`命中排行榜缓存: ${key}`);
        return JSON.parse(data);
      }

      return null;
    } catch (error: any) {
      this.logger.error(`获取排行榜缓存失败:`, error?.message || error);
      return null;
    }
  }

  /**
   * 清除排行榜缓存
   */
  async clearRankingsCache(gameType: GameType): Promise<void> {
    try {
      const pattern = `${this.keyPrefix}rankings:${gameType}:*`;
      const keys = await this.redisService.keys(pattern);

      for (const key of keys) {
        await this.redisService.del(key);
      }
      this.logger.debug(`清除排行榜缓存: ${keys.length} 个键`);
    } catch (error: any) {
      this.logger.error(`清除排行榜缓存失败:`, error?.message || error);
    }
  }

  // ==================== 游戏状态缓存 ====================

  /**
   * 缓存游戏状态
   */
  async cacheGameState(gameType: GameType, data: any): Promise<void> {
    try {
      const key = `${this.keyPrefix}state:${gameType}`;
      const ttl = casinoConfig.redis.ttl.gameState;

      await this.redisService.set(key, JSON.stringify(data), ttl);
      this.logger.debug(`缓存游戏状态: ${key}, TTL: ${ttl}秒`);
    } catch (error: any) {
      this.logger.error(`缓存游戏状态失败:`, error?.message || error);
    }
  }

  /**
   * 获取缓存的游戏状态
   */
  async getCachedGameState(gameType: GameType): Promise<any | null> {
    try {
      const key = `${this.keyPrefix}state:${gameType}`;
      const data = await this.redisService.get(key);

      if (data) {
        this.logger.debug(`命中游戏状态缓存: ${key}`);
        return JSON.parse(data);
      }

      return null;
    } catch (error: any) {
      this.logger.error(`获取游戏状态缓存失败:`, error?.message || error);
      return null;
    }
  }

  // ==================== 下注统计缓存 ====================

  /**
   * 缓存下注统计
   */
  async cacheBetStatistics(roundId: number, data: any): Promise<void> {
    try {
      const key = `${this.keyPrefix}stats:${roundId}`;
      const ttl = casinoConfig.redis.ttl.roundInfo;

      await this.redisService.set(key, JSON.stringify(data), ttl);
      this.logger.debug(`缓存下注统计: ${key}, TTL: ${ttl}秒`);
    } catch (error: any) {
      this.logger.error(`缓存下注统计失败:`, error?.message || error);
    }
  }

  /**
   * 获取缓存的下注统计
   */
  async getCachedBetStatistics(roundId: number): Promise<any | null> {
    try {
      const key = `${this.keyPrefix}stats:${roundId}`;
      const data = await this.redisService.get(key);

      if (data) {
        this.logger.debug(`命中下注统计缓存: ${key}`);
        return JSON.parse(data);
      }

      return null;
    } catch (error: any) {
      this.logger.error(`获取下注统计缓存失败:`, error?.message || error);
      return null;
    }
  }

  // ==================== 缓存管理 ====================

  /**
   * 获取缓存统计信息
   */
  async getCacheStats(): Promise<{
    totalKeys: number;
    memoryUsage: string;
    hitRate: number;
  }> {
    try {
      // 内存缓存不直接暴露Redis的info，所以这里只返回内存缓存的大小
      return {
        totalKeys: 0, // RedisService does not expose this directly
        memoryUsage: "N/A",
        hitRate: 0,
      };
    } catch (error: any) {
      this.logger.error(`获取缓存统计失败:`, error?.message || error);
      return {
        totalKeys: 0,
        memoryUsage: "0B",
        hitRate: 0,
      };
    }
  }

  /**
   * 清理过期缓存
   */
  async cleanupExpiredCache(): Promise<number> {
    try {
      const now = Date.now();
      let cleanedCount = 0;
      // RedisService does not have a direct cleanupExpired method for TTLs
      // This method would typically iterate through keys and check TTLs if RedisService supported it.
      // For now, it's a placeholder.
      this.logger.log(
        `RedisService does not have a direct cleanupExpired method for TTLs. No keys will be cleaned.`
      );
      return 0;
    } catch (error: any) {
      this.logger.error(`清理过期缓存失败:`, error?.message || error);
      return 0;
    }
  }

  /**
   * 预热缓存
   */
  async warmupCache(): Promise<void> {
    try {
      this.logger.log("开始预热缓存...");

      // 预热当前期数信息
      const gameTypes = [
        GameType.DICE,
        GameType.CHIBI,
        GameType.ROCK_PAPER_SCISSORS,
      ];
      for (const gameType of gameTypes) {
        const key = `${this.keyPrefix}state:${gameType}`;
        const exists = await this.redisService.exists(key);
        if (!exists) {
          // 设置默认状态
          const defaultState = {
            currentRound: null,
            lastUpdate: Date.now(),
          };
          await this.redisService.set(
            key,
            JSON.stringify(defaultState),
            casinoConfig.redis.ttl.gameState
          );
        }
      }

      this.logger.log("缓存预热完成");
    } catch (error: any) {
      this.logger.error(`缓存预热失败:`, error?.message || error);
    }
  }
}
